#pragma once

#include <nanobdd/Bdd.h>
#include <nanobdd/Cache.h>
#include <nanobdd/Common.h>
#include <nanobdd/NodeTable.h>
#include <nanobdd/ListApplyCache.h>

namespace nanobdd {

class Nanobdd {
 public:
  Nanobdd(size_t tableSize, size_t bucketSize, size_t cacheSize);
  Bdd& createVar(int id);
  void createVars(int num);
  static Bdd& getVar(int id);

  Node* makeNode(int level, Node* low, Node* high);

  Bdd bddAnd(const Bdd& x, const Bdd& y);

  Bdd bddOr(const Bdd& x, const Bdd& y);

  Bdd bddNot(const Bdd& x);

  Bdd negCof(const Bdd& x, int id) const;

  Bdd posCof(const Bdd& x, int id) const;

  static inline Node* trueNode;
  static inline Node* falseNode;

 private:
  Node* combine(size_t x, const Bdd& low, Bdd& high);

  static inline std::vector<Bdd> vars_;
  NodeTable nodeTable_;
  int cacheSize_;
  Cache cache_;
  // ListApplyCache cache_;
};

} // namespace nanobdd